import {
	App,
	Plugin,
	PluginSettingTab,
	Setting,
	Notice,
	FileSystemAdapter,
} from "obsidian";
import * as fs from "fs";
import * as path from "path";

// 定义插件设置接口
interface BackgroundSettings {
	backgroundImagePath: string;
	opacity: number;
	blur: number;
	contrast: number;
	saturate: number;
	brightness: number;
}

// 默认设置
const DEFAULT_SETTINGS: BackgroundSettings = {
	backgroundImagePath: "",
	opacity: 0.2,
	blur: 0,
	contrast: 1,
	saturate: 2,
	brightness: 2,
};

const getConfigDir = (app: App, pluginId: string) => {
	if (app.vault.adapter instanceof FileSystemAdapter) {
		const basePath = app.vault.adapter.getBasePath();
		if (basePath) {
			return path.join(
				basePath,
				app.vault.configDir,
				"plugins",
				pluginId,
				"data"
			);
		}
	}
	return "";
};

/**
 * 获取文件的 MIME 类型（针对图片）
 * @param filePath 图片文件路径
 * @returns MIME 类型字符串（如 image/png）
 */
function getImageMimeType(filePath: string): string {
	const ext = path.extname(filePath).toLowerCase();
	const mimeMap: Record<string, string> = {
		".png": "image/png",
		".jpg": "image/jpeg",
		".jpeg": "image/jpeg",
		".gif": "image/gif",
		".svg": "image/svg+xml",
		".webp": "image/webp",
		".bmp": "image/bmp",
	};
	return mimeMap[ext] || "application/octet-stream";
}

/**
 * 判断文件是否存在
 * @param path 文件目录地址
 * @returns true存在，false不存在
 */
const pathExists = (path: string) => {
	try {
		return fs.existsSync(path);
	} catch (err) {
		return false;
	}
};

/**
 * 将单张图片转换为 Base64 编码（带 MIME 前缀）
 * @param imagePath 图片文件的绝对路径
 * @returns 完整的 Base64 字符串（如 ...）
 */
const imageToBase64 = (imagePath: string) => {
	if (pathExists(imagePath)) {
		const fileContent = fs.readFileSync(imagePath);
		const base64Str = fileContent.toString("base64");
		const mimeType = getImageMimeType(imagePath);
		return `data:${mimeType};base64,${base64Str}`;
	}
	return "none";
};

export default class CustomBackgroundPlugin extends Plugin {
	settings: BackgroundSettings;
	private styleElement: HTMLElement | null = null;
	private imagesDir: string;
	private pluginBackgroundSettingTab: BackgroundSettingTab;

	async onload() {
		const pluginId = this.manifest.id;
		const pluginDataDir = getConfigDir(this.app, pluginId);
		this.imagesDir = path.join(pluginDataDir, "images");

		this.ensureDirectoryExists(this.imagesDir);
		await this.loadSettings();
		this.createStyleElement();
		this.applyBackgroundSettings();

		this.pluginBackgroundSettingTab = new BackgroundSettingTab(
			this.app,
			this
		);

		// 添加设置面板和命令
		this.addSettingTab(this.pluginBackgroundSettingTab);
		this.addCommand({
			id: "upload-background-image",
			name: "上传背景图片",
			callback: () => this.uploadImage(),
		});

		console.log("自定义背景插件已加载");
	}

	onunload() {
		// 移除样式元素，避免残留
		if (this.styleElement && this.styleElement.parentElement) {
			this.styleElement.parentElement.removeChild(this.styleElement);
		}
		console.log("自定义背景插件已卸载");
	}

	// 确保目录存在，不存在则创建（支持多级目录）
	private ensureDirectoryExists(dirPath: string) {
		if (!fs.existsSync(dirPath)) {
			fs.mkdirSync(dirPath, { recursive: true });
		}
	}

	// 加载保存的设置（合并默认值）
	async loadSettings() {
		this.settings = { ...DEFAULT_SETTINGS, ...(await this.loadData()) };
	}

	// 保存设置并实时更新背景
	async saveSettings() {
		await this.saveData(this.settings);
		this.applyBackgroundSettings();
	}

	// 创建样式元素（避免重复添加）
	private createStyleElement() {
		// 先删除旧样式，再创建新样式
		if (this.styleElement && this.styleElement.parentElement) {
			this.styleElement.parentElement.removeChild(this.styleElement);
		}
		this.styleElement = document.createElement("style");
		this.styleElement.id = "custom-background-styles";
		document.head.appendChild(this.styleElement);
	}

	private getImageBase64(): string {
		if (!this.settings.backgroundImagePath) return "none";
		const fullPath = path.join(
			this.imagesDir,
			this.settings.backgroundImagePath
		);
		return imageToBase64(fullPath);
	}

	// 应用背景样式到页面
	private applyBackgroundSettings() {
		if (!this.styleElement) return;
		const backgroundImage = this.getImageBase64();

		this.styleElement.textContent = `
      body {
        --background-opacity: ${this.settings.opacity};
        --background-image-blur: ${this.settings.blur}px;
        --background-image-contrast: ${this.settings.contrast};
        --background-image-saturate: ${this.settings.saturate};
        --background-image-brightness: ${this.settings.brightness};
        --default-app-image: ${backgroundImage !== "none" ? `url("${backgroundImage}")` : "none"
			};
      }
      
      body::before {
        content: "";
        position: fixed;
        background-image: var(--default-app-image);
        background-position: center center;
        background-attachment: fixed;
        background-size: cover;
        background-repeat: no-repeat;
        height: 100%;
        width: 100%;
        filter: blur(var(--background-image-blur))
          contrast(var(--background-image-contrast))
          saturate(var(--background-image-saturate))
          brightness(var(--background-image-brightness));
        opacity: var(--background-opacity);
        z-index: calc(var(--layer-menu) + 1);
        pointer-events: none;
        transition: all 0.3s ease;
      }
    `;
	}

	// 上传图片（公开方法，供设置面板调用）
	public uploadImage() {
		const input = document.createElement("input");
		input.type = "file";
		input.accept = "image/*";

		input.onchange = async (e: Event) => {
			const target = e.target as HTMLInputElement;
			if (!target.files || target.files.length === 0) return;

			const file = target.files[0];
			try {
				const timestamp = Date.now();
				const extension = path.extname(file.name).toLowerCase();
				const fileName = `background-${timestamp}${extension}`;
				const destinationPath = path.join(this.imagesDir, fileName);


				const arrayBuffer = await file.arrayBuffer();
				fs.writeFileSync(destinationPath, Buffer.from(arrayBuffer));

				if (this.settings.backgroundImagePath) {
					const oldImagePath = path.join(
						this.imagesDir,
						this.settings.backgroundImagePath
					);
					if (fs.existsSync(oldImagePath))
						fs.unlinkSync(oldImagePath);
				}

				// 更新设置并刷新界面
				this.settings.backgroundImagePath = fileName;
				await this.saveSettings();
				new Notice("背景图片已更新！");
				this.pluginBackgroundSettingTab.display();
			} catch (error) {
				console.error("保存图片失败:", error);
				new Notice("保存图片失败！");
			}
		};

		input.click();
	}

	// 获取预览图URL（供设置面板使用）
	public getPreviewUrl(): string | null {
		return this.settings.backgroundImagePath ? this.getImageBase64() : null;
	}

	// 删除当前背景图片（供设置面板调用）
	public async deleteCurrentImage() {
		if (this.settings.backgroundImagePath) {
			const imagePath = path.join(
				this.imagesDir,
				this.settings.backgroundImagePath
			);
			if (fs.existsSync(imagePath)) fs.unlinkSync(imagePath);

			this.settings.backgroundImagePath = "";
			await this.saveSettings();
			new Notice("背景图片已删除");
		}
	}
}

// 设置面板类
class BackgroundSettingTab extends PluginSettingTab {
	plugin: CustomBackgroundPlugin;

	constructor(app: App, plugin: CustomBackgroundPlugin) {
		super(app, plugin);
		this.plugin = plugin;
	}

	display(): void {
		const { containerEl } = this;
		containerEl.empty();

		// 面板标题
		containerEl.createEl("h2", { text: "自定义背景设置" });

		// 图片上传与删除
		const imageSetting = new Setting(containerEl)
			.setName("背景图片")
			.setDesc("上传笔记的背景的图片");

		// 选择图片按钮
		imageSetting.addButton((btn) =>
			btn
				.setButtonText("选择图片")
				.onClick(() => this.plugin.uploadImage())
		);

		// 有图片时显示删除按钮（橙色警告样式）
		if (this.plugin.settings.backgroundImagePath) {
			imageSetting.addButton((btn) =>
				btn
					.setButtonText("删除图片")
					.setWarning()
					.onClick(async () => {
						await this.plugin.deleteCurrentImage();
						this.display();
					})
			);
		}

		// 图片预览
		const previewUrl = this.plugin.getPreviewUrl();
		if (previewUrl) {
			const previewContainer = containerEl.createDiv();
			previewContainer.style.margin = "10px 0";

			const previewImg = previewContainer.createEl("img");
			previewImg.src = previewUrl;
			previewImg.style.maxWidth = "200px";
			previewImg.style.maxHeight = "200px";
			previewImg.style.border =
				"1px solid var(--background-modifier-border)";
			previewImg.style.borderRadius = "4px";
		}

		// 不透明度设置（0.0-1.0）
		const opacitySettingContainer = containerEl.createDiv({ cls: "background-replacement-slider-container" });
		const opacitySettingAddButton = opacitySettingContainer.createEl("button", { text: "+" });
		const bopacitySettingReduceButton = opacitySettingContainer.createEl("button", { text: "-" });


		new Setting(containerEl)
			.setName("不透明度")
			.setDesc(`背景图片的不透明度 (0.0 - 1.0)，当前设置的值为：${this.plugin.settings.opacity}`)
			.addSlider((slider) => {
				opacitySettingContainer.insertBefore(slider.sliderEl, opacitySettingAddButton);

				return slider
					.setLimits(0, 1, 0.01)
					.setValue(this.plugin.settings.opacity)
					.onChange(async (val) => {
						this.plugin.settings.opacity = val;
						await this.plugin.saveSettings();
						this.display();
					})
			}).controlEl.replaceChildren(opacitySettingContainer);


		opacitySettingAddButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.opacity + 0.01;
			newVal = Math.min(1, newVal);
			this.plugin.settings.opacity = Number(newVal.toFixed(2));
			await this.plugin.saveSettings();
			this.display();
		});

		bopacitySettingReduceButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.opacity - 0.01;
			newVal = Math.max(0, newVal);
			this.plugin.settings.opacity = Number(newVal.toFixed(2));
			await this.plugin.saveSettings();
			this.display();
		});

		// 模糊度设置（0-20px）
		const blurSettingContainer = containerEl.createDiv({ cls: "background-replacement-slider-container" });
		const blurSettingAddButton = blurSettingContainer.createEl("button", { text: "+" });
		const blurSettingReduceButton = blurSettingContainer.createEl("button", { text: "-" });



		new Setting(containerEl)
			.setName("模糊度")
			.setDesc(`背景图片的模糊程度 (0 - 20px)，当前设置的值为：${this.plugin.settings.blur}`)
			.addSlider((slider) => {
				blurSettingContainer.insertBefore(slider.sliderEl, blurSettingAddButton);

				return slider
					.setLimits(0, 20, 1)
					.setValue(this.plugin.settings.blur)
					.onChange(async (val) => {
						this.plugin.settings.blur = val;
						await this.plugin.saveSettings();
						this.display();
					})
			}).controlEl.replaceChildren(blurSettingContainer);

		blurSettingAddButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.blur + 1;
			newVal = Math.min(20, newVal);
			this.plugin.settings.blur = newVal;
			await this.plugin.saveSettings();
			this.display();
		});

		blurSettingReduceButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.blur - 1;
			newVal = Math.max(0, newVal);
			this.plugin.settings.blur = newVal;
			await this.plugin.saveSettings();
			this.display();
		});

		// 对比度设置（0.0-5.0）
		const contrastSettingContainer = containerEl.createDiv({ cls: "background-replacement-slider-container" });
		const contrastSettingAddButton = contrastSettingContainer.createEl("button", { text: "+" });
		const contrastSettingReduceButton = contrastSettingContainer.createEl("button", { text: "-" });



		new Setting(containerEl)
			.setName("对比度")
			.setDesc(`背景图片的对比度 (0.0 - 5.0)，当前设置的值为：${this.plugin.settings.contrast}`)
			.addSlider((slider) => {
				contrastSettingContainer.insertBefore(slider.sliderEl, contrastSettingAddButton);

				return slider
					.setLimits(0, 5, 0.1)
					.setValue(this.plugin.settings.contrast)
					.onChange(async (val) => {
						this.plugin.settings.contrast = val;
						await this.plugin.saveSettings();
						this.display();
					})
			}).controlEl.replaceChildren(contrastSettingContainer);

		contrastSettingAddButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.contrast + 0.1;
			newVal = Math.min(5, newVal);
			this.plugin.settings.contrast = Number(newVal.toFixed(1));
			await this.plugin.saveSettings();
			this.display();
		});

		contrastSettingReduceButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.contrast - 0.1;
			newVal = Math.max(0, newVal);
			this.plugin.settings.contrast = Number(newVal.toFixed(1));
			await this.plugin.saveSettings();
			this.display();
		});

		// 饱和度设置（0.0-5.0）
		const saturateSettingContainer = containerEl.createDiv({ cls: "background-replacement-slider-container" });
		const saturateSettingAddButton = saturateSettingContainer.createEl("button", { text: "+" });
		const saturateSettingReduceButton = saturateSettingContainer.createEl("button", { text: "-" });



		new Setting(containerEl)
			.setName("饱和度")
			.setDesc(`背景图片的饱和度 (0.0 - 5.0)，当前设置的值为：${this.plugin.settings.saturate}`)
			.addSlider((slider) => {
				saturateSettingContainer.insertBefore(slider.sliderEl, saturateSettingAddButton);

				return slider
					.setLimits(0, 5, 0.1)
					.setValue(this.plugin.settings.saturate)
					.onChange(async (val) => {
						this.plugin.settings.saturate = val;
						await this.plugin.saveSettings();
						this.display();

					})
			}).controlEl.replaceChildren(saturateSettingContainer);

		saturateSettingAddButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.saturate + 0.1;
			newVal = Math.min(5, newVal);
			this.plugin.settings.saturate = Number(newVal.toFixed(1));
			await this.plugin.saveSettings();
			this.display();
		});

		saturateSettingReduceButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.saturate - 0.1;
			newVal = Math.max(0, newVal);
			this.plugin.settings.saturate = Number(newVal.toFixed(12));
			await this.plugin.saveSettings();
			this.display();
		});


		// 亮度设置（0.0-5.0）
		const brightnessSettingContainer = containerEl.createDiv({ cls: "background-replacement-slider-container" });
		const brightnessSettingAddButton = brightnessSettingContainer.createEl("button", { text: "+" });
		const brightnessSettingReduceButton = brightnessSettingContainer.createEl("button", { text: "-" });



		new Setting(containerEl)
			.setName("亮度")
			.setDesc(`背景图片的亮度 (0.0 - 5.0)，当前设置的值为：${this.plugin.settings.brightness}`)
			.addSlider((slider) => {
				brightnessSettingContainer.insertBefore(slider.sliderEl, brightnessSettingAddButton);
				return slider
					.setLimits(0, 5, 0.1)
					.setValue(this.plugin.settings.brightness)
					.onChange(async (val) => {
						this.plugin.settings.brightness = val;
						await this.plugin.saveSettings();
						this.display();
					})
			}).controlEl.replaceChildren(brightnessSettingContainer);


		brightnessSettingAddButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.brightness + 0.1;
			newVal = Math.min(5, newVal);
			this.plugin.settings.brightness = Number(newVal.toFixed(1));
			await this.plugin.saveSettings();
			this.display();
		});

		brightnessSettingReduceButton.addEventListener("click", async () => {
			let newVal = this.plugin.settings.brightness - 0.1;
			newVal = Math.max(0, newVal);
			this.plugin.settings.brightness = Number(newVal.toFixed(12));
			await this.plugin.saveSettings();
			this.display();
		});
	}
}
